﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Web.Script.Serialization;
using System.Xml;
using HalAfstande.Domain.Objects;

namespace HalAfstande.Domain
{
    public class DataHandler
    {
        public MapInfo Map { get; private set; }
        public List<Hal> Haller { get; set; }
        readonly XmlDocument _halXml = new XmlDocument();
        private readonly XmlNamespaceManager _nsmgr;

        public DataHandler(string origin, string dataLocation)
        {
            _halXml.Load(AppDomain.CurrentDomain.BaseDirectory + dataLocation);
            _nsmgr = new XmlNamespaceManager(_halXml.NameTable);
            _nsmgr.AddNamespace("msn", "http://www.woodbase.dk/HalListe");
            Haller = LoadHalData(_nsmgr);
            RequestHalDistanceInfo(origin, Haller);
        }

        private static void RequestHalDistanceInfo(string origin, IEnumerable<Hal> haller)
        {
            MapInfo map;
            foreach (var hal in haller)
            {
                var webRequest =
                    (HttpWebRequest)
                    WebRequest.Create(
                        string.Format("http://maps.googleapis.com/maps/api/distancematrix/json?origins=" + origin + "&destinations={0}&mode=driving&language=da-DK&sensor=false", hal.Address));
                var response = (HttpWebResponse)webRequest.GetResponse();
                var ser = new JavaScriptSerializer();
                var streamContent = response.GetResponseStream();
                if (streamContent == null) throw new InvalidDataException("No content found in map stream! Trying to load:" + hal.Name);
                var stream = new StreamReader(streamContent);
                var json = stream.ReadToEnd();
                map = ser.Deserialize<MapInfo>(json);
                foreach (var element in map.Rows[0].Elements)
                {
                    if (element.Distance != null)
                        hal.DistanceInKm = element.Distance.Text;
                    hal.DistanceInTime = element.Duration.Text;
                    if (element.Distance != null) hal.Distance = int.Parse(element.Distance.Value.ToString());
                }
            }
        }

        private List<Hal> LoadHalData(XmlNamespaceManager ns)
        {
            var haller = new List<Hal>();
            var halList = _halXml.SelectNodes("//msn:Hal", _nsmgr);
            if (halList != null)
                foreach (XmlNode node in halList)
                {
                    if (node.Attributes == null) continue;
                    var name = node.Attributes["name"].Value;
                    var addressNode = node.SelectSingleNode("msn:Address/msn:Street", ns);
                    var cityNode = node.SelectSingleNode("msn:Address/msn:City", ns);
                    var postalCodeNode = node.SelectSingleNode("msn:Address/msn:PostalCode", ns);
                    if (name != null && addressNode != null && cityNode != null && postalCodeNode != null)
                        haller.Add(new Hal()
                                       {
                                           Address = addressNode.InnerText + ", " + postalCodeNode.InnerText + " " + cityNode.InnerText,
                                           Name = name
                                       });
                }
            return haller;
        }

        public void BuildExportFile(Referee referee, string fileName)
        {
            var f = new FileInfo(fileName);
            if (!f.Directory.Exists)
            {
                f.Directory.Create();
            }
            using (var exportFile = new FileStream(fileName, FileMode.Create))
            {
                using (var writer = new StreamWriter(exportFile, Encoding.UTF8))
                {
                    writer.WriteLine(string.Format("Dommernummer;{0};", referee.RefereeNumber));
                    writer.WriteLine(string.Format("Navn;{0};", referee.Name));
                    writer.WriteLine(string.Format("Adresse;{0};", referee.Address));
                    writer.WriteLine(string.Format("Postnr.;{0};By;{1};", referee.PostalCode, referee.City));
                    writer.WriteLine();
                    writer.WriteLine(string.Format("Halnavn;Adresse;Afstand i km;Afstand (tur/retur);Afstand i tid;"));
                    foreach (var hal in Haller)
                    {
                        Debug.WriteLine(((double)(hal.Distance * 2) / 1000));
                        writer.WriteLine(string.Format("{0};{1};{2};{4} km;{3};",
                                                       hal.Name, hal.Address, hal.DistanceInKm, hal.DistanceInTime, ((double)(hal.Distance * 2) / 1000).ToString("f1")));
                    }
                }
            }
        }
    }
}